/*
 * Copyright (c) 2008-2016, RF-Embedded GmbH
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef CPPRFEPROTOCOLHANDLER_H
#define CPPRFEPROTOCOLHANDLER_H

#include "../types.h"

#include <vector>
#include <string>

#include "CPPrfeProtocolConstants.h"
#include "CPPrfeMessageQueue.h"
#include "CPPrfeTagEvent.h"
#include "../CPPrfeReaderInterface.h"
#include "../device/IProtocolDeviceInterface.h"
#include "../helper/StringHelper.h"
#include "../helper/Array.h"

namespace CPPrfeReaderInterface
{

    class CPPrfeProtocolHandler : public IProtocolDeviceInterface::DataReadListener
    {
        class TagEvent;

    public:
        CPPrfeProtocolHandler(IProtocolDeviceInterface* device);
        virtual ~CPPrfeProtocolHandler();
        void close();

        bool getReaderID(ulong& readerID);
        bool getReaderType(ulong& readerType);
        bool getHardwareRevision(ulong& hardwareRevision);
        bool getSoftwareRevision(ulong& softwareRevision);
        bool getBootloaderRevision(ulong& bootloaderRevision);
        bool getCurrentSystem(eRFE_CURRENT_SYSTEM& currentSystem);
        bool getCurrentState(eRFE_CURRENT_READER_STATE& currentState);
        bool getStatusRegister ( ulonglong& statusRegister );
        bool getAntennaCount(byte& count);

        bool getAttenuation(ushort& maxAttenuation, ushort& currentAttenuation);
        bool getFrequency(byte& mode, byte& maxFrequencyCount, std::vector<uint> &frequencies);
        bool getSensitivity( short& maxSensitivity, short& minSensitivity, short& currentSensitivity );
        bool getLbtParams(ushort& listenTime, ushort& idleTime, ushort& maxAllocTime, short& rssiThreshold);
        bool setAttenuation(ushort value);

        bool reboot();
        bool setHeartBeat(bool on, ushort interval);
        bool setAntennaPower(bool on);
        bool saveSettingsPermanent();
        bool restoreFactorySettings();
        bool getParam(ushort address, std::vector<byte>& value);

        bool getGPIOCaps(ulong& mask, ulong& output, ulong& input);
        bool getGPIODirection(ulong& direction);
        bool getGPIO(ulong& mask);

        bool doSingleInventory(std::vector<CPPrfeTagEvent> &tagList);
        bool setCyclicInventory(bool on);
        bool readFromTag(std::vector<byte> epc, byte mem_bank, ushort address, std::vector<byte> passwd, byte count, std::vector<byte>& data);
        bool writeToTag(std::vector<byte> epc, byte mem_bank, ushort address, std::vector<byte> passwd, std::vector<byte> data);
        bool lockTag(std::vector<byte> epc, byte mode, byte memory, std::vector<byte> password);
        bool killTag(std::vector<byte> epc, byte rfu, byte recom, std::vector<byte> password);

    //*********************************************************************** Getter & Setter
    public:
        eRFE_RET_VALUE lastReturnCode() const;

        int responseTimeOut() const;
        void setResponseTimeOut(int responseTimeOut);

        bool blockCyclicInventoryInterrupts() const;
        void setBlockCyclicInventoryInterrupts(bool blockCyclicInventoryInterrupts);

        int minimumTraceLevel() const;
        void setMinimumTraceLevel(int minimumTraceLevel);

    //*********************************************************************** Output
    protected:
        bool send2Reader(byte com1, byte com2);
        bool send2Reader(byte com1, byte com2, std::vector<byte> payload);

    //*********************************************************************** Input
    protected:
        virtual void heartBeatISR(const std::vector<byte>& payload);
        virtual void cyclicInventoryISR(const std::vector<byte>& payload);
        virtual void stateChangedISR(const std::vector<byte>& payload);
        virtual void statusRegChangedISR ( const std::vector<byte>& payload );
        virtual void gpioValuesChangedISR ( const std::vector<byte>& payload );
        virtual void notificationISR(const std::vector<byte>& payload);
        virtual void aplicationISR(const std::vector<byte>& payload);
        void operationResultISR(const std::vector<byte>& payload);

    private:
        void initParser()
        {
           _state = START_BYTE_1;
           _payloadIndex = 0;
           _payloadLength = 0;
        }

        /// <summary>
        /// State of the state machine to parse received data
        /// </summary>
        eMessageState               _state;
        /// <summary>
        /// Current single message
        /// </summary>
        std::vector<byte>           _singleMsg;
        /// <summary>
        /// Current payload index
        /// </summary>
        int                         _payloadIndex;
        /// <summary>
        /// Current paylod length
        /// </summary>
        int                         _payloadLength;


        virtual void dataReadHandler(const std::vector<byte> &data);
        void computeMessage(const std::vector<byte>& msg);


    //*********************************************************************** Helper
    protected:

        ushort messageId(byte command1, byte command2);
        byte calcXORCS(std::vector<byte> data);

    //*********************************************************************** TagEvent
    private:
        bool parseTagEvent(const std::vector<byte>& payload, CPPrfeTagEvent& tagEvent);

    //*********************************************************************** EventListener
    public:
        class EventListener {
        public:
            /// <summary>
            /// Delegate is called every time a heratbeat signal of the reader is received.
            /// </summary>
            virtual void HeartBeatHandler(const std::vector<byte>& data) = 0;

            /// <summary>
            /// Delegate is called everytime a result of the cyclic inventory is received.
            /// </summary>
            /// <param name="tagEvent">The data of the tag event</param>
            virtual void CyclicInventoryHandler(const CPPrfeTagEvent& tagEvent) = 0;

            /// <summary>
            /// Delegate is called everytime the reader changed its state.
            /// </summary>
            /// <param name="newState">The new state of the reader</param>
            virtual void StateChangedHandler(eRFE_CURRENT_READER_STATE newState) = 0;

            /// <summary>
            /// Delegate is called everytime the status register of the reader changed.
            /// </summary>
            /// <param name="statusRegister">New value of the status register</param>
            virtual void StatusRegisterChangedHandler(ulonglong statusRegister) = 0;

            /// <summary>
            /// Delegate is called everytime the status register of the reader changed.
            /// </summary>
            /// <param name="gpioValues">New value of GPIO status</param>
            virtual void GpioValuesChangedHandler(ulong gpioValues) = 0;

            /// <summary>
            /// Delegate is called everytime a notification is received.
            /// </summary>
            virtual void NotificationHandler(const std::vector<byte>& payload) = 0;

            /// <summary>
            /// Delegate is called everytime a application event is received.
            /// </summary>
            virtual void ApplicationEventHandler(const std::vector<byte>& payload) = 0;
        };

        void setEventListener(CPPrfeProtocolHandler::EventListener *eventListener);



    //*********************************************************************** Member
    protected:
        void initMember()
        {
            _ResponseTimeOut = 1000;
            _BlockCyclicInventoryInterrupts = false;
            _MinimumTraceLevel = 3;
            m_eventListener = 0;
        }

        EventListener* m_eventListener;

        /*!
         \brief Private member to store received messages according to the message id.
         */
        CPPrfeMessageQueue _MessageQueue;

        /// <summary>
        /// Private member to store received pending messages according to the message id.
        /// </summary>
        CPPrfeMessageQueue _PendingMessageQueue;

        /// <summary>
        /// Instance of the device that is used to communicate with the reader.
        /// </summary>
        IProtocolDeviceInterface*  _Device;

        /// <summary>
        /// The last return code of the reader.
        /// </summary>
        eRFE_RET_VALUE _LastReturnCode;

        /// <summary>
        /// The time out in ms to wait for the response of the reader.
        /// </summary>
        int _ResponseTimeOut;

        /// <summary>
        /// Option to block interrupts from cyclic inventory.
        /// </summary>
        bool _BlockCyclicInventoryInterrupts;

        /// <summary>
        /// Minimum used trace level for traces inside this class
        /// </summary>
        int _MinimumTraceLevel;
    };

}
#endif // CPPRFEPROTOCOLHANDLER_H
